#include "Naview.h"
#include "StringOps.h"
#include "Neptuner.h"

#include<iostream>

using namespace std;

#include "Keywords.h"
#include "Scope.h"
#include "Symbol.h"
#include "SymbolTable.h"
#include "Tokenizer.h"
#include "Ark.h"

Naview::Naview(void): m_pxOut(&std::cout)
{
	m_pxCurrentScope = NULL;
	m_eScopeType = Scope::eScopeInvalid;
	m_sFilename = "";
	m_sOutputFile = "";
	m_nLines = 0;
	m_nLevel = 0;
}

Naview::~Naview(void)
{
	if(m_sOutputFile!="")
		delete m_pxOut;
}

void Naview::setOutputFile(std::string sOutFile)
{
	sOutFile = sOutFile + ".uboat.html";
	Neptuner_createDirectoryFor(sOutFile);
	m_pxOut =  new std::ofstream(sOutFile.c_str());
	m_sOutputFile = sOutFile;
}


void Naview::offScopeEntry(Scope& inNewScope, Scope& inOldScope)
{
	m_pxCurrentScope = &inNewScope;
	m_eScopeType = m_pxCurrentScope->getScopeType();
	createSpanForScope();
}

void Naview::offScopeExit(Scope& inNewScope, Scope& inOldScope)
{
	createSpanEnd();
	m_pxCurrentScope = &inNewScope;
	m_eScopeType = m_pxCurrentScope->getScopeType();
}

void Naview::offNewToken(Scope& inScope, Token& inToken)
{
	std::string sTokenHTML="";
	
	for(size_t i=0; i<inToken.m_sValue.length(); i++)
	{
		char cTest = inToken.m_sValue[i];

		switch (cTest) 
		{
			case '&':
				sTokenHTML += "&amp;";
				break;
			case '<':
				sTokenHTML += "&lt;";
				break;
			case '>':
				sTokenHTML += "&gt;";
				break;
			case '"':
				sTokenHTML += "&quot;";
				break;
			case '\t':
				sTokenHTML += "&nbsp;&nbsp;&nbsp;&nbsp;"; 
				//TODO: Replace with string padding function
				break;
			case ' ':
				sTokenHTML += "&nbsp;";
				break;
			case '\r':
				sTokenHTML = ""; //Otherwise \r\n sequences will produce two <BR/>s 
				//TODO: Replace with lookahead strategy
				break;
			case '\n':
				sTokenHTML ="<BR/>";
				break;
			default:
				sTokenHTML += cTest;
				break;
		}
	}

	switch( m_eScopeType)
	{
	case Scope::eScopeCommentC:
	case Scope::eScopeCommentCPP:
	case Scope::eScopePreprocessor:
	case Scope::eScopeLiteral:
		break;

	default:
		if(Keywords::isKeyword(sTokenHTML))
		{
			sTokenHTML = ("<span class=kwrd>" + sTokenHTML + "</span>");
		}
		else
		{
			if(inToken.m_bIsDelimiter) break;

			Symbol xSymbol;
			if(inScope.findSymbol(inToken.m_sValue, xSymbol))
			{
				//<a href="#bookmark">HTML a tag example</a> 
				sTokenHTML="";
				sTokenHTML += "<a href='";
				if(m_pxLocation->m_sFilename != xSymbol.m_xDefinition.m_sFilename)
				{
					std::string sTargetFile = Ark_getCodebaseLocation(xSymbol.m_xDefinition.m_sFilename);
					sTargetFile += ".uboat.html";
					std::string sRelativizer = Neptuner_getRelativizer(m_nLevel)+"codebase/";
					sTargetFile = sRelativizer + sTargetFile;

					sTokenHTML += sTargetFile;
				}
				
				sTokenHTML += "#SL";
				sTokenHTML += stringify(xSymbol.m_xDefinition.m_nLineNumber);
				sTokenHTML += "'>";
				sTokenHTML += inToken.m_sValue;
				sTokenHTML += "</a>";
			}
		}
	}

    *m_pxOut<<sTokenHTML;

	char cDelimiter = char(inToken);
	if('\n' == cDelimiter)
		//Intentionally not coupling with switch case, this is not tr functionality
	{
		createNewline();
	}

}

void Naview::createNewline()
{
std::string sRelativizer = Neptuner_getRelativizer(m_nLevel)+"uboat/";
	createSpanEnd();

	std::string sLineHTML="";
	sLineHTML += "</span></li>\n";
	sLineHTML += "<li><img src='" + sRelativizer+ "code.png' class='clicker'/><span  class='sl' id= 'SL";
	sLineHTML += stringify(m_pxLocation->m_nLineNumber);
	sLineHTML += "'>";
	*m_pxOut<<sLineHTML<<endl;

	createSpanForScope();
}

void Naview::createSpanForScope()
{
	switch(m_eScopeType)
	{
	case Scope::eScopeCommentC:
	case Scope::eScopeCommentCPP:
		*m_pxOut << "<span class=comm>";
		break;

	case Scope::eScopePreprocessor:
		*m_pxOut << "<span class=prep>";
		break;

	case Scope::eScopeLiteral:
		*m_pxOut << "<span class=litr>";
		break;
	}
}

void Naview::createSpanEnd()
{
	switch(m_eScopeType)
	{
	case Scope::eScopeCommentC:
	case Scope::eScopeCommentCPP:
	case Scope::eScopePreprocessor:
	case Scope::eScopeLiteral:
		*m_pxOut<< "</span>";
		break;
	}
}

void Naview::generateHeader(){
std::string sNeptunerHome = Neptuner_getRelativizer(m_nLevel);
std::string sRelativizer = sNeptunerHome +"uboat/";

*m_pxOut<<"<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>"<<endl;
*m_pxOut<<"<html>"<<endl;
*m_pxOut<<"<head>"<<endl;
*m_pxOut<<"<title>"<< m_sFilename << "</title>"<<endl;
*m_pxOut <<"<link rel='shortcut icon' type='image/ico' href='"<<sRelativizer<<"neptunerIcon.jpg'>"<<endl;

*m_pxOut<<"<link rel='stylesheet' href='" << sRelativizer << "neptuner.css' type='text/css' media='screen'>"<<endl;
*m_pxOut<<"<link rel='stylesheet' href='" << sRelativizer << "uboat.css' type='text/css' media='screen'>"<<endl;
*m_pxOut<<"<link rel='stylesheet' href='" << sRelativizer << "menu.css' type='text/css' media='screen'>"<<endl;

*m_pxOut<<"<script type='text/javascript' src='" << sRelativizer << "prototype.js'> </script>"<<endl;
*m_pxOut<<"<script type='text/javascript' src='" << sRelativizer << "editinplace.js'> </script>"<<endl;
*m_pxOut<<"<script type='text/javascript' src='" << sRelativizer << "inplacenote.js'> </script>"<<endl;
*m_pxOut<<"<script type='text/javascript' src='" << sRelativizer << "protofish.js'> </script>"<<endl;
*m_pxOut<<"<script type='text/javascript' src='" << sRelativizer << "proto.menu.js'> </script>"<<endl;
*m_pxOut<<"<script type='text/javascript' src='" << sRelativizer << "saver.js'> </script>"<<endl;
*m_pxOut<< "<script type='text/javascript'>var nSourceLines = "<< m_nLines<<";";
*m_pxOut<<"var sUBoatHome='"<<sRelativizer<<"';";
*m_pxOut<<"var sNeptunerHome='"<<sNeptunerHome<<"';";
*m_pxOut<<"var sFilename='"<<m_sFilename<<"';";
*m_pxOut<<"</script>"<<endl;
*m_pxOut<<"</head>"<<endl;
}

void Naview::generateBody()
{
std::string sRelativizer = Neptuner_getRelativizer(m_nLevel)+"uboat/";
*m_pxOut<<"<body>"<<endl;
*m_pxOut<<"<script type='text/javascript' src='" << sRelativizer << "uboat.js'></script>"<<endl;
	generatePaneUBoat();
	generatePaneSidebar();
	generatePaneSource();
}

void Naview::generatePaneUBoat()
{
std::string sRelativizer = Neptuner_getRelativizer(m_nLevel)+ "uboat/";
*m_pxOut<<"<div id=paneUBoat>"<<endl;
*m_pxOut<<"<div id=barTitle><img id='menuNeptuner' src='" << sRelativizer << "neptunerIcon.jpg'></img>"<<endl;
*m_pxOut<<"<strong>"<<getFilename(m_sFilename)<<"</strong></div>"<<endl;
*m_pxOut<<"<BR/>"<<endl;
*m_pxOut<<"<div id=barMenu>"<<endl;
*m_pxOut<<"<ul id='menuUBoat' class='menu'>"<<endl;
*m_pxOut<<"						<li><a class='sub'>File</a>"<<endl;
*m_pxOut<<"							<ul>"<<endl;
*m_pxOut<<"								<li onClick='saveFile()'><span class='last'><a href='#'>Save</a></span></li>"<<endl;
*m_pxOut<<"								<li><a class='sub' role='menuitem'>Export</a>"<<endl;
*m_pxOut<<"									<ul>"<<endl;
*m_pxOut<<"										<li><a>Notes</a></li>"<<endl;
*m_pxOut<<"										<li><a>Bookmarks</a></li>"<<endl;
*m_pxOut<<"										<li><a>Code</a></li>"<<endl;
*m_pxOut<<"									</ul>"<<endl;
*m_pxOut<<"								</li>"<<endl;
*m_pxOut<<" 							</ul>"<<endl;
*m_pxOut<<"						</li>"<<endl;
*m_pxOut<<"						<li><span class='sub'><a class='sub' href='#'>View</a>"<<endl;
*m_pxOut<<"							<ul>"<<endl;
*m_pxOut<<"								<li><a onClick='toggleInlineNotes()'>Notes Inline</a></li>"<<endl;
*m_pxOut<<"								<li><a>Unhide All</a></li>"<<endl;
*m_pxOut<<"								<li><span class='last'><a onClick='toggleLineNumbers()'>Line Numbers</a></span></li>"<<endl;
*m_pxOut<<"							</ul>"<<endl;
*m_pxOut<<"						</span></li>"<<endl;
*m_pxOut<<"						<li><span class='sub'><a class='sub' href='#'>Edit</a>"<<endl;
*m_pxOut<<"							<ul>"<<endl;
*m_pxOut<<"								<li><a  role='menuitem' class='sub'>Remove</a>"<<endl;
*m_pxOut<<"									<ul role='menu'>"<<endl;
*m_pxOut<<"										<li><a role='menuitem'>Bookmarks</a></li>"<<endl;
*m_pxOut<<"										<li><span class='last'><a>Notes</a></span></li>"<<endl;
*m_pxOut<<"									</ul>"<<endl;
*m_pxOut<<"								</li>"<<endl;
*m_pxOut<<"							</ul>"<<endl;
*m_pxOut<<"						</span></li>"<<endl;
*m_pxOut<<"</ul>"<<endl;
*m_pxOut<<"</div>"<<endl;
*m_pxOut<<"<div id='areaBookmarks'>"<<endl;
*m_pxOut<<"<img src='" << sRelativizer << "bookmark.png'> Bookmarks</img>"<<endl;
*m_pxOut<<"<ul id=listBookmarks>"<<endl;
*m_pxOut<<"</ul>"<<endl;
*m_pxOut<<"</div>"<<endl;
*m_pxOut<<"<div id=dispScrapbook>"<<endl;
*m_pxOut<<"<img src='" << sRelativizer << "note.png'> Notes</img>"<<endl;
*m_pxOut<<"<ul id=listScraps></ul>"<<endl;
*m_pxOut<<"</div>"<<endl;
*m_pxOut<<"<div id=barStatus>"<<endl;
*m_pxOut<<"</div>"<<endl;
*m_pxOut<<"</div>"<<endl;
}

void Naview::generatePaneSidebar()
{
std::string sRelativizer = Neptuner_getRelativizer(m_nLevel)+"uboat/";
*m_pxOut<<"<div id=paneSidebar>"<<endl;
*m_pxOut<<"	<span id='sideBarTab'><img src='" << sRelativizer << "slidea.png' alt='sideBar' title='sideBar' onclick='toggleSidebar()'/></span>"<<endl;
*m_pxOut<<"	<div id='sideBarContents'>"<<endl;
*m_pxOut<<"		<div id='sideBarContentsInner'>"<<endl;
*m_pxOut<<"			<form id=formGotoLine>"<<endl;
*m_pxOut<<"			Line: <input type='text' size=5 id=inpLine>"<<endl;
*m_pxOut<<"			<input type='button' value='Goto' onclick='gotoLine()'>"<<endl;
*m_pxOut<<"			</form>"<<endl;
*m_pxOut<<"			<form id=formScrap>"<<endl;
*m_pxOut<<"			<textarea cols='30' name='comments' rows='3' id='textareaScrap'>What's on your mind?</textarea>"<<endl;
*m_pxOut<<"			<BR/>"<<endl;
*m_pxOut<<"			Add To:"<<endl;
*m_pxOut<<"			<input type='button' value='Scrapbook ' onclick='addScrap()'>"<<endl;
*m_pxOut<<"			<input type='button' value='Line' onclick='addInlineNote()'>"<<endl;
*m_pxOut<<"			<br/>"<<endl;
*m_pxOut<<"			</form>"<<endl;
*m_pxOut<<"		</div>"<<endl;
*m_pxOut<<"	</div>"<<endl;
*m_pxOut<<"</div>"<<endl;
}

void Naview::generatePaneSource()
{
std::string sRelativizer = Neptuner_getRelativizer(m_nLevel)+"uboat/";
*m_pxOut<<"<div id=paneSource>"<<endl;
*m_pxOut<<"<ol>"<<endl;
*m_pxOut<<"<li><img src='"<<sRelativizer<<"code.png' class='clicker'/><span class='sl' id= 'SL1'>"<<endl;
//The rest to be filled in dynamically, during the walk
}

void Naview::generateFooter()
{
*m_pxOut<< "</span></li>" << endl;
*m_pxOut<< "</ol>" << endl;
*m_pxOut<<"</div>"<<endl;
*m_pxOut<< "</body>" << endl << "</html>" << endl;

}